﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;


namespace TP2.Lib
{
    [Serializable] //parala serializacion binaria
    public class Mision
    {

        #region /*------------- Propiedades ----------------*/

        private int[] _dimensiones = new int[3];
        public int[] Dimensiones
        {
            get { return this._dimensiones; }
            set { this._dimensiones = value; }
        }

        private List<ElementoJuego> _elementosAliados = new List<ElementoJuego>();
        public List<ElementoJuego> ElementosAliados
        {
            get { return this._elementosAliados;}
            set {this._elementosAliados = value;}
        }

        private List<ElementoJuego> _elementosEnemigos = new List<ElementoJuego>();
        public List<ElementoJuego> ElementosEnemigos
        {
            get { return this._elementosEnemigos; }
        }

        private List<ElementoJuego> _armasVoladorasAliadas = new List<ElementoJuego>();
        public List<ElementoJuego> ArmasVoladorasAliadas
        {
            get { return this._armasVoladorasAliadas;}
        }

        private List<ElementoJuego> _armasVoladorasEnemigas = new List<ElementoJuego>();
        public List<ElementoJuego> ArmasVoladorasEnemigas
        {
            get { return this._armasVoladorasEnemigas; }
        }

        private List<ElementoJuego> _elementosEstaticos = new List<ElementoJuego>();
        public List<ElementoJuego> ElementosEstaticos
        {
           get {return this._elementosEstaticos;}
        }

        bool _fin;
        public bool Fin
        {
            get {return this._fin;}
            set { this._fin = value; }
        }
        
        #endregion

        private Mision() { } /*Contructor vacio, lo utiliza la serialización xml*/
        
        public Mision(int[] dimensiones)
        {
            this.Dimensiones = dimensiones;
            this.Fin = false;
        }

        public void AgregarFlotaEnemiga(Flota unaFlota)
        {
            foreach (AvionEnemigo avion in unaFlota.Aviones)
            {
                this.AgregarElementosEnemigos(avion);
            }
        }

        public void AgregarElementosAliados(AvionJugador avionJugador)
        {
            this.ElementosAliados.Add(avionJugador);
        }

        public void AgregarElementosEnemigos(AvionEnemigo avionEnemigo)
        {
            this.ElementosEnemigos.Add(avionEnemigo);
        }

        public void AgregarArmasVoladorasAliadas(Proyectil proyectil)
        {
            this.ArmasVoladorasAliadas.Add(proyectil);
        }

        public void AgregarArmasVoladorasEnemigas(Proyectil proyectil)
        {
            this.ArmasVoladorasEnemigas.Add(proyectil);
        }
                
        public void AgregarElementosEstaticos(ElementoJuego elementoJuego)
        {
            this.ElementosEstaticos.Add(elementoJuego);
        }                

        public void ChequearPosicion(double[] posicion)
        {
            if ((posicion[0] > this.Dimensiones[0]) && (posicion[1] > this.Dimensiones[1]))
            {
                throw new Exception();
            }
        }
        
        /*Chequea el estado actual de todos los objetos*/
        public void ChequearEstadoDeLaMision()
        {
            //Elimina elementos destruidos
            this.ChequearIntegridad();
            //Compara si hubo choques entre Aliados (jugador/es) y Enemigos
            this.ChequearColisiones(this.ElementosAliados, this.ElementosEnemigos);

            this.EvaluarColisionEntreProyectilAliadoYAvionEnemigo();
            this.EvaluarColisionEntreProyectilesEnemigoYJugadores();
            this.EvaluarColisionEntreJugadoresYElementosEstaticos();
            this.EvaluarFinalDeLaMision();
        }

        public void ProcesarLista(List<ElementoJuego> listaDeMision)
        {
            //Acomoda a cada Elemento en su respectiva Lista
            foreach (VehiculoAereo vehiculo in listaDeMision)
            {
                vehiculo.AgregateALista(this.ElementosAliados, this.ElementosEnemigos);
            }


            if (this.ElementosAliados.Count == 0) // no iria antes de hacer el foreach?
            {
                throw new Exception();
            }

        }

        /// <summary>
        /// Simula un turno de cada objeto haciendolo actuar
        /// </summary>
        public void SimularTurno()
        {
            Proyectil proyectil;

            this.ChequearEstadoDeLaMision();

            if (this.ArmasVoladorasAliadas.Count != 0)
            {
                // Ver si hay que recorrer la lista al reves
                foreach (Proyectil proyectilAliado in this.ArmasVoladorasAliadas)
                {
                    proyectilAliado.Actuar();
                }
            }

            if (this.ElementosEnemigos.Count != 0)
            {
                // Ver si hay que recorrer la lista al reves
                foreach (VehiculoAereo enemigo in this.ElementosEnemigos) // Cambie AvionEnemigo por VehiculoAereo por tema de AvionCivil
                {
                    proyectil = enemigo.Actuar();
                    if (proyectil != null)
                    {
                        this.ArmasVoladorasEnemigas.Add(proyectil);
                    }
                }
            }

            if (this.ArmasVoladorasEnemigas.Count != 0)
            {
                // Ver si hay que recorrer la lista al reves
                foreach (Proyectil proyectilEnemigo in this.ArmasVoladorasEnemigas)
                {
                    proyectilEnemigo.Actuar();
                }
            }
        }
        
        #region /*------Metodos Privados -----*/

        private int ChequearColisionesEntreArmasAliadasYElementosEnemigos()
        {
            double distancia;
            int puntos = 0;

            foreach (Proyectil proyectilAliado in this.ArmasVoladorasAliadas)
            {
                foreach (VehiculoAereo enemigo in this.ElementosEnemigos)// Cambio AvionEnemigo por VehiculoAereo
                {
                    distancia = proyectilAliado.CalcularDistanciaEntreElementos(enemigo);
                    if (distancia <= 0)
                    {
                        proyectilAliado.Impactar(enemigo);
                        enemigo.Impactar(proyectilAliado);
                        puntos = this.EvaluarAccionDelEnemigo(enemigo);
                        if (!enemigo.EstoyVivo())
                        {
                            ElementoJuego elementoDejado;
                            elementoDejado = enemigo.MeMori();
                            if (elementoDejado != null)
                            {
                                this.ElementosEstaticos.Add(elementoDejado);
                            }
                        }
                    }
                }
            }
            return (puntos);
        }

        /*Elimina elementos que ya fueron destruidos.*/
        private bool ChequearIntegridad()
        {
            if (this.ElementosAliados.Count == 0)
            {
                //Caso que no existan Aviones Aliados (Jugador)
                return (false);
                throw new Exception();
            }
            else
            {
                //Limpiar elementos muertos de la lista de aliados
                this.LimpiarListaDeAliados();
                //Limpiar elementos muertos de la lista de enemigos
                this.LimpiarListaDeEnemigos();
                //Limpiar proyectiles destruidos de la lista de proyectilesAliados
                this.LimpiarListaDeProyectilesAliados();
                //Limpiar proyectiles destruidos de la lista de proyectiles enemigos
                this.LimpiarListaDeProyectilesEnemigos();
                //Limpiar elementos estaticos: tanques de energia y armas
                this.LimpiarListaDeElementosEstaticos();

                return (true);
            }
        }

        private void LimpiarListaDeProyectilesEnemigos()
        {
            for (int index = this.ArmasVoladorasEnemigas.Count - 1; index >= 0; index--)
            {
                if (!(((Proyectil)this.ArmasVoladorasEnemigas[index]).EstoyVivo()))
                {
                    this.ArmasVoladorasEnemigas.Remove(((Proyectil)this.ArmasVoladorasEnemigas[index]));
                }
            }
        }

        private void LimpiarListaDeProyectilesAliados()
        {
            for (int index = this.ArmasVoladorasAliadas.Count - 1; index >= 0; index--)
            {
                if (!(((Proyectil)this.ArmasVoladorasAliadas[index]).EstoyVivo()))
                {
                    this.ArmasVoladorasAliadas.Remove(((Proyectil)this.ArmasVoladorasAliadas[index]));
                }
            }
        }

        private void LimpiarListaDeElementosEstaticos()
        {
            for (int index = this.ElementosEstaticos.Count - 1; index >= 0; index--)
            {
                if (!(((ElementoJuego)this.ElementosEstaticos[index]).EstoyVivo()))
                {
                    this.ElementosEstaticos.Remove(((ElementoJuego)this.ElementosEstaticos[index]));
                }
            }
        }

        private void LimpiarListaDeAliados()
        {
            for (int index = this.ElementosAliados.Count - 1; index >= 0; index--)
            {
                if (!(((AvionJugador)this.ElementosAliados[index]).EstoyVivo()))
                {
                    this.ElementosAliados.Remove(((AvionJugador)this.ElementosAliados[index]));
                }
            }
        }

        private void LimpiarListaDeEnemigos()
        {
            for (int index = this.ElementosEnemigos.Count - 1; index >= 0; index--)
            {
                if (!(((VehiculoAereo)this.ElementosEnemigos[index]).EstoyVivo()))
                {
                    this.ElementosEnemigos.Remove(((VehiculoAereo)this.ElementosEnemigos[index]));
                }
            }
        }

        private int EvaluarAccionDelEnemigo(VehiculoAereo elemento)
        {
            int puntos = 0;

            if (!elemento.EstoyVivo())
            {
                puntos += elemento.PuntosPorDestruccion;

                if (typeof(AvionEnemigo) == elemento.GetType())
                {
                    //evaluo lo que sucede si el avion muerto era un guia
                    this.EvaluarAccionDelGuia(elemento);
                    //evaluo lo que sucede si el avion muerto otorgaba alguno de los bonus
                    this.EvaluarBonus(elemento);
                }
            }
            return puntos;
        }

        private void EvaluarBonus(VehiculoAereo enemigo)
        {
            ElementoJuego elementoDejado = enemigo.MeMori();
            //Chequeo si el avion dejo algun elemento al morir
            if (elementoDejado != null)
            {
                this.AgregarElementosEstaticos(elementoDejado);
            }
        }

        private void EvaluarAccionDelGuia(VehiculoAereo enemigo)
        {
            if (enemigo.EsGuia)
            {
                //me traigo a los aviones de la flota de la cual murio el guia
                List<AvionEnemigo> flota;
                flota = enemigo.FlotaALaQuePertenece.Aviones;
                foreach (AvionEnemigo avion in flota)
                {
                    avion.Huir();
                }
            }
        }

        private void EvaluarFinalDeLaMision()
        {
            foreach (AvionJugador jugador in this.ElementosAliados)
            {
                /*Con que alguno de los jugadores haya alcanzado el maximo puntaje es suficiente para dar por finalizada la mision*/
                this.Fin = ((this.Fin) || (jugador.PuntosAcumulados >= 1000));
            }
        }

        private void EvaluarColisionEntreJugadoresYElementosEstaticos()
        {
            if (this.ElementosEstaticos.Count != 0)
            {
                //busca si hubo choques entre Jugadores y Elementos Estaticos
                this.ChequearColisiones(this.ElementosAliados, this.ElementosEstaticos);
            }
        }

        private void EvaluarColisionEntreProyectilesEnemigoYJugadores()
        {
            if (this.ArmasVoladorasEnemigas.Count != 0)
            {
                //busca si hubo choques entre Jugadores y ArmasVoladorasEnemigas
                this.ChequearColisiones(this.ElementosAliados, this.ArmasVoladorasEnemigas);
            }
        }

        private void EvaluarColisionEntreProyectilAliadoYAvionEnemigo()
        {
            if (this.ArmasVoladorasAliadas.Count != 0)
            {
                //Compara si hubo choques entre ProyectilesAliados y Enemigos
                int puntos = this.ChequearColisionesEntreArmasAliadasYElementosEnemigos();
                //Actualizo puntos de los jugadores
                foreach (AvionJugador jugador in this.ElementosAliados)
                {
                    jugador.ActualizaPuntos(puntos);
                }
            }
        }

        /*chequea si hay colisiones entre los elementos de dos listas*/
        private void ChequearColisiones(List<ElementoJuego> lista1, List<ElementoJuego> lista2)
        {
            double distancia;

            foreach (ElementoJuego elementoDeL1 in lista1)
            {
                foreach (ElementoJuego elementoDeL2 in lista2)
                {
                    distancia = elementoDeL1.CalcularDistanciaEntreElementos(elementoDeL2);
                    if (distancia <= 0)
                    {
                        elementoDeL1.Impactar(elementoDeL2);
                        elementoDeL2.Impactar(elementoDeL1);
                    }
                }
            }
        }




        #endregion
    }
}
